#include "Token.h"
#include <cstdio>
#include <cctype>
#include <iostream>
#include <string>
using namespace std;
Token::Token() {
	tokenString = "";
	type = Token::INIT;
}
static Token::TokenType genType(const string &tokenString) {
	if (tokenString.compare("const") == 0) {
		return Token::CONSTTK;
	}else if(tokenString.compare("int") == 0) {
		return Token::INTTK;
	}
	else if (tokenString.compare("char") == 0) {
		return Token::CHARTK;
	}
	else if (tokenString.compare("void") == 0) {
		return Token::VOIDTK;
	}
	else if(tokenString.compare("main") == 0) {
		return Token::MAINTK;
	}
	else if (tokenString.compare("if") == 0) {
		return Token::IFTK;
	}
	else if (tokenString.compare("else") == 0) {
		return Token::ELSETK;
	}
	else if (tokenString.compare("do") == 0) {
		return Token::DOTK;
	}
	else if (tokenString.compare("while") == 0) {
		return Token::WHILETK;
	}
	else if (tokenString.compare("for") == 0) {
		return Token::FORTK;
	}
	else if (tokenString.compare("scanf") == 0) {
		return Token::SCANFTK;
	}
	else if (tokenString.compare("printf") == 0) {
		return Token::PRINTFTK;
	}
	else if (tokenString.compare("return") == 0) {
		return Token::RETURNTK;
	}
	else {
		return Token::IDENFR;
	}
}
static Token::TokenType genType(char ch) {
	switch (ch)
	{
	case '+':
		return Token::PLUS;
	case '-':
		return Token::MINU;
	case '*':
		return Token::MULT;
	case '/':
		return Token::DIV;
	case ';':
		return Token::SEMICN;
	case ',':
		return Token::COMMA;
	case '(':
		return Token::LPARENT;
	case ')':
		return Token::RPARENT;
	case '[':
		return Token::LBRACK;
	case ']':
		return Token::RBRACK;
	case '{':
		return Token::LBRACE;
	case '}':
		return Token::RBRACE;
	default:
		return Token::ERROR;
		break;
	}
}
int Token::init(char*& str) {
	tokenString = "";
	type = INIT;
	while (isspace(str[0])) {
		str++;
	}
	if (str[0] == '\0') {
		return 0;
	}
	if (isalpha(str[0]) || str[0] == '_') {
		while (isalnum(str[0]) || str[0] == '_') {
			tokenString += str[0];
			str++;
		}
		this->type = genType(tokenString);
	}
	else if (isdigit(str[0])) {
		while (isdigit(str[0])) {
			tokenString += str[0];
			str++;
		}
		this->type = INTCON;
	}
	else if (str[0] == '\'') {
		tokenString = str[1];
		str += 3;
		this->type = CHARCON;
	}
	else if(str[0]=='\"'){
		str++;
		while (str[0] != '\"') {
			tokenString += str[0];
			str++;
		}
		str++;
		this->type = STRCON;
	}
	else if (str[0] == '<') {
		tokenString += str[0];
		str++;
		this->type = LSS;
		if (str[0] == '=') {
			tokenString += str[0];
			str++;
			this->type = LEQ;
		}
	}
	else if (str[0] == '>') {
		tokenString += str[0];
		str++;
		this->type = GRE;
		if (str[0] == '=') {
			tokenString += str[0];
			str++;
			this->type = GEQ;
		}
	}
	else if (str[0] == '!') {
		tokenString += str[0];
		str++;
		this->type = NOT;
		if (str[0] == '=') {
			tokenString += str[0];
			str++;
			this->type = NEQ;
		}
	}
	else if (str[0] == '=') {
		tokenString += str[0];
		str++;
		this->type = ASSIGN;
		if (str[0] == '=') {
			tokenString += str[0];
			str++;
			this->type = EQL;
		}
	}
	else {
		this->type = genType(str[0]);
		tokenString += str[0];
		str++;
	}
	return 1;
}
const void Token::show() {
	static const char* TokenTypeString[] = {
	"INIT",
	"IDENFR",
	"INTCON",
	"CHARCON",
	"STRCON",
	"CONSTTK",
	"INTTK",
	"CHARTK",
	"VOIDTK",
	"MAINTK",
	"IFTK",
	"ELSETK",
	"DOTK",
	"WHILETK",
	"FORTK",
	"SCANFTK",
	"PRINTFTK",
	"RETURNTK",
	"PLUS",
	"MINU",
	"MULT",
	"DIV",
	"LSS",
	"LEQ",
	"GRE",
	"GEQ",
	"EQL",
	"NEQ",
	"ASSIGN",
	"SEMICN",
	"COMMA",
	"LPARENT",
	"RPARENT",
	"LBRACK",
	"RBRACK",
	"LBRACE",
	"RBRACE",
	"NOT",
	"ERROR"
	};
	cout << TokenTypeString[this->type]/* << "consttkis:"<<CONSTTK*/ << ' ' << tokenString << endl;
}

const Token::TokenType Token::getType()
{
	return this->type;
}
